﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using shenghua.Authorization;
using shenghua.Basics.Feedbacks.Dto;
using shenghua.Common.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace shenghua.Basics.Feedbacks
{
    public class FeedbackAppService : shenghuaAppServiceBase
    {
        private readonly FeedbackManager _feedbackManager;
        private readonly IRepository<Feedback> _feedbackRepository;

        public FeedbackAppService(
            FeedbackManager feedbackManager,
            IRepository<Feedback> feedbackRepository
            )
        {
            _feedbackManager = feedbackManager;
            _feedbackRepository = feedbackRepository;
        }

        public async Task<FeedbackDto> Create(CreateFeedbackDto input)
        {
            var item = new Feedback();
            input.MapTo(item);
            await _feedbackManager.Create(item);
            return ObjectMapper.Map<FeedbackDto>(item);
        }

        [AbpAuthorize(PermissionNames.FeedbackManagement)]
        public async Task<FeedbackDto> Update(UpdateFeedbackDto input)
        {
            var item = await _feedbackManager.Get(input.Id);
            input.MapTo(item);
            await _feedbackManager.Update(item);
            return ObjectMapper.Map<FeedbackDto>(item);
        }

        [AbpAuthorize(PermissionNames.FeedbackManagement)]
        [HttpPost]
        public async Task Delete(BatchIntIdDto input)
        {
            foreach(int id in input.Ids)
            {
                await _feedbackManager.Delete(id);
            }
        }

        [AbpAuthorize(PermissionNames.FeedbackManagement)]
        public async Task Audited(BatchIntIdDto input)
        {
            foreach(int id in input.Ids)
            {
                await _feedbackManager.Audit(id, FeedbackStatus.Audited);
            }
        }

        [AbpAuthorize(PermissionNames.FeedbackManagement)]
        public async Task AuditFailed(BatchIntIdDto input)
        {
            foreach (int id in input.Ids)
            {
                await _feedbackManager.Audit(id, FeedbackStatus.AuditFailed);
            }
        }

        public async Task<PagedResultDto<FeedbackDto>> Search(SearchFeedbackDto input)
        {
            var query = handleSearch(input);

            int totalCount = query.Count();
            var items = query.OrderByDescending(r => r.CreationTime).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            return new PagedResultDto<FeedbackDto>
            {
                TotalCount = totalCount,
                Items = items.Select(r => ObjectMapper.Map<FeedbackDto>(r)).ToList()
            };
        }

        public async Task<PagedResultDto<FeedbackDto>> SearchAudited(SearchFeedbackDto input)
        {
            var query = handleSearch(input);
            query = query.Where(r => r.Status == FeedbackStatus.Audited);

            int totalCount = query.Count();
            var items = query.OrderByDescending(r => r.CreationTime).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            return new PagedResultDto<FeedbackDto>
            {
                TotalCount = totalCount,
                Items = items.Select(r => ObjectMapper.Map<FeedbackDto>(r)).ToList()
            };
        }

        private IQueryable<Feedback> handleSearch(SearchFeedbackDto input)
        {
            var query = _feedbackRepository.GetAll();

            if(input.FeedbackStatus != null && (int)input.FeedbackStatus != -1)
            {
                query = query.Where(r => r.Status == input.FeedbackStatus);
            }

            if(input.ReplyStatus == FeedbackReplyStatus.PendingReply)
            {
                query = query.Where(r => !r.IsReplied);
            }
            else if(input.ReplyStatus == FeedbackReplyStatus.Replied)
            {
                query = query.Where(r => r.IsReplied);
            }
            
            if (!string.IsNullOrWhiteSpace(input.Search))
            {
                switch (input.SearchTarget)
                {
                    case "name": query = query.Where(r => r.Name == input.Search); break;
                    case "content": query = query.Where(r => r.Content.Contains(input.Search)); break;
                    case "phoneNumber": query = query.Where(r => r.PhoneNumber == input.Search); break;
                    case "emailAddress": query = query.Where(r => r.EmailAddress == input.Search); break;
                }
            }

            if(input.BeginTime != null)
            {
                query = query.Where(r => r.CreationTime >= input.BeginTime);
            }

            if (input.EndTime != null)
            {
                query = query.Where(r => r.CreationTime <= input.EndTime);
            }

            return query;
        }
    }
}
